package org.tiny.autounit.core.data.transport.server.handler;

import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import lombok.extern.slf4j.Slf4j;
import org.tiny.autounit.core.data.transport.server.domain.MessageType;
import org.tiny.autounit.core.data.transport.server.domain.NettyMessage;
import org.tiny.autounit.core.data.transport.server.domain.NettyRequest;
import org.tiny.autounit.core.data.transport.server.domain.NettyResponse;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author shichaoyang
 * @Description: 服务端处理rpc请求
 * @date 2019-02-24 12:57
 */
@Slf4j
public class ServerHandler extends ChannelInboundHandlerAdapter {

    private ExecutorService executorService = Executors.newFixedThreadPool(10);

    /**
     * 服务端接收到客户端的请求
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //开启业务线程池进行处理
        executorService.submit(() -> {
            //接收到的请求进行还原
            NettyMessage message = (NettyMessage) msg;
            //如果此包属于业务处理包
            if (message != null && message.getType() == MessageType.SERVICE_REQ.value()) {
                //设置回应数据包
                NettyMessage<NettyResponse> response = new NettyMessage();
                response.setType(MessageType.SERVICE_RESP.value());
                response.setBody(new NettyResponse());

                NettyMessage<NettyRequest> request = (NettyMessage) msg;
                response.getBody().setRequestId(request.getBody().getRequestId());

                try {
                    //反射调用方法，并将结果放入回应数据包中
                    NettyResponse result = handle(request.getBody());
                    response.setBody(result);
                } catch (Throwable t) {
                    response.getBody().setError(t);
                }
                //将回应数据包推送到缓冲区
                ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
            }
        });
    }

    /**
     * 反射调用方法并得到结果
     * @param request
     * @return
     * @throws Throwable
     */
    private NettyResponse handle(NettyRequest request) throws Throwable {
        //将调用结果封装并返回
        NettyResponse response = new NettyResponse();
        response.setResult("");
        response.setRequestId(request.getRequestId());
        return response;
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        log.error("服务端异常，服务端Socket[" + ctx.channel().localAddress().toString() + "], 客户端Socket[" + ctx.channel().remoteAddress().toString() + "]", cause);
        ctx.close();
    }

}
